Gatsby - 使用 gatsby-transformer-remark 轉換 Markdown 文件

2022-03-01 Tue

介紹 gatsby-transformer-remark

在使用 gatsby-source-filesystem 插件讓 Gatsby 知道要讀取哪些目錄下的文件後。

我們還需要使用 gatsby-transformer-remark 這個插件,將 Markdown (.md) 文件轉換為可供 GraphQL 查詢的資料節點 (nodes)。

安裝 gatsby-transformer-remark

首先使用以下指令安裝 gatsby-transformer-remark:

npm install gatsby-transformer-remark

配置 gatsby-config.js

gatsby-config.js 中的 plugins 陣列內新增 gatsby-transformer-remark:

module.exports = {
  plugins: [
    // 其他插件...
    `gatsby-transformer-remark`],
}

準備測試用 Markdown 文件

假設我們的項目目錄結構如下,在 src/pages/markdown-article/ 目錄下有一個 test.md 文件:

├─components
│ Banner.js
│ Footer.js  
│ Header.js
│ Layout.js
│ Navbar.js
│
├─images
│ banner-night.jpg
│ icon.png
│  
├─pages
│ │ 404.js
│ │ about.js
│ │ index.js
│ │ tech-page.js
│ │
│ └─markdown-article
│     test.md
│
└─styles
    banner.module.scss
    footer.module.scss
    global.scss
    layout.module.scss
    usage.module.scss
    _mixin.scss

test.md 文件的內容如下:

---
title: 這是我第二個標題
stack: 這是我第二個副標  
slug: MySecondSlug
ImageHD: ../hdImages/bear.jpg
---

# 這個是我的第二冊是檔案

**lorem loremloremloremloremloremloremloremloremlorem**,QQ

<p>test</p>

<b>kkkk</b>

上面的內容包含了一些 Markdown 語法和 HTML 語法,同時在文件開頭使用了 FrontMatter 設定了一些元數據。

使用 GraphQL 查詢轉換後的資料

接下來我們可以在瀏覽器中開啟 http://localhost:8000/___graphql 進入 GraphQL 操作 playground,輸入以下查詢:

query {
  allMarkdownRemark {
    nodes {
      html
      frontmatter {
        slug
        stack
        title
      }
    }
  }
}

執行後可以看到查詢結果如下:

{
  "data": {
    "allMarkdownRemark": {
      "nodes": [
        {
          "html": "<h1>這個是我的第二冊是檔案</h1>\n<p><strong>lorem loremloremloremloremloremloremloremloremlorem</strong>,QQ</p>\n<p>test</p>\r\n<b>kkkk</b>",
          "frontmatter": {
            "slug": "MySecondSlug",
            "stack": "這是我第二個副標",
            "title": "這是我第二個標題"
          }
        }
      ]
    }
  }"extensions": {}
}

查詢結果包含了 Markdown 文件的 HTML 內容以及我們在 FrontMatter 中設定的元數據。

在 React 組件中獲取資料

最後,我們可以在某個 React 組件中使用 pageQuery 的方式獲取上述查詢的資料

import React from 'react'
import { graphql } from 'gatsby'

const MyPage = ({ data }) => {
  const { html, frontmatter } = data.allMarkdownRemark.nodes[0]
  const { slug, stack, title } = frontmatter

  return (
    <div>
      <h1>{title}</h1>
      <div dangerouslySetInnerHTML={{ __html: html }} />
    </div>
  )
}

export const query = graphql`
  query {
    allMarkdownRemark {
      nodes {
        html
        frontmatter {
          slug
          stack
          title   
        }
      }
    }
  }
`

export default MyPage

需要注意的是由於安全性考量,React 不建議直接渲染 HTML 字串,因此我們使用 dangerouslySetInnerHTML 這個較不安全的方式注入 HTML。在 production 階段中需要特別小心,避免潛在的 XSS 攻擊風險。詳細內容可以觀看以下相關資源

相關資源